package org.dromara.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dromara.app.domain.AppRole;
import org.dromara.app.domain.AppUserRole;
import org.dromara.app.domain.bo.AppRoleBo;
import org.dromara.app.domain.vo.AppRoleVo;
import org.dromara.app.mapper.AppRoleMapper;
import org.dromara.app.mapper.AppUserRoleMapper;
import org.dromara.app.service.AppRoleService;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * App端角色信息Service业务层处理
 *
 * @author ruoyi
 * @date 2024-01-01
 */
@Service
public class AppRoleServiceImpl extends ServiceImpl<AppRoleMapper, AppRole> implements AppRoleService {

    @Autowired
    private AppUserRoleMapper userRoleMapper;

    /**
     * 查询App端角色信息
     */
    @Override
    public AppRoleVo queryById(Long roleId) {
        return baseMapper.selectVoById(roleId);
    }

    /**
     * 查询App端角色信息列表
     */
    @Override
    public TableDataInfo<AppRoleVo> queryPageList(AppRoleBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AppRole> lqw = buildQueryWrapper(bo);
        Page<AppRoleVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询App端角色信息列表
     */
    @Override
    public List<AppRoleVo> queryList(AppRoleBo bo) {
        LambdaQueryWrapper<AppRole> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<AppRole> buildQueryWrapper(AppRoleBo bo) {
        LambdaQueryWrapper<AppRole> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getRoleName()), AppRole::getRoleName, bo.getRoleName());
        lqw.eq(StringUtils.isNotBlank(bo.getRoleKey()), AppRole::getRoleKey, bo.getRoleKey());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), AppRole::getStatus, bo.getStatus());
        lqw.orderByAsc(AppRole::getRoleSort);
        return lqw;
    }

    /**
     * 新增App端角色信息
     */
    @Override
    public Boolean insertByBo(AppRoleBo bo) {
        AppRole add = BeanUtil.toBean(bo, AppRole.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setRoleId(add.getRoleId());
        }
        return flag;
    }

    /**
     * 修改App端角色信息
     */
    @Override
    public Boolean updateByBo(AppRoleBo bo) {
        AppRole update = BeanUtil.toBean(bo, AppRole.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(AppRole entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除App端角色信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // 校验角色是否存在用户关联
            for (Long id : ids) {
                long count = countUserRoleByRoleId(id);
                if (count > 0) {
                    AppRoleVo role = queryById(id);
                    throw new RuntimeException(String.format("角色%s已分配用户,不能删除", role.getRoleName()));
                }
            }
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据用户ID查询角色
     */
    @Override
    public List<AppRoleVo> selectRolesByUserId(Long userId) {
        return baseMapper.selectRolesByUserId(userId);
    }

    /**
     * 根据用户ID获取角色权限
     */
    @Override
    public Set<String> selectRolePermissionByUserId(Long userId) {
        Set<String> perms = baseMapper.selectRolePermissionByUserId(userId);
        return perms;
    }

    /**
     * 查询所有角色
     */
    @Override
    public List<AppRoleVo> selectRoleAll() {
        return baseMapper.selectRoleAll();
    }

    /**
     * 根据用户ID获取角色选择框列表
     */
    @Override
    public List<Long> selectRoleListByUserId(Long userId) {
        return baseMapper.selectRoleListByUserId(userId);
    }

    /**
     * 校验角色名称是否唯一
     */
    @Override
    public boolean checkRoleNameUnique(String roleName) {
        return baseMapper.checkRoleNameUnique(roleName) == 0;
    }

    /**
     * 校验角色权限是否唯一
     */
    @Override
    public boolean checkRoleKeyUnique(String roleKey) {
        return baseMapper.checkRoleKeyUnique(roleKey) == 0;
    }

    /**
     * 校验角色是否允许操作
     */
    @Override
    public boolean checkRoleAllowed(Long roleId) {
        return roleId != null && roleId != 1L;
    }

    /**
     * 校验角色是否有数据权限
     */
    @Override
    public boolean checkRoleDataScope(Long roleId) {
        return roleId != null && roleId != 1L;
    }

    /**
     * 通过角色ID查询角色使用数量
     */
    @Override
    public long countUserRoleByRoleId(Long roleId) {
        return userRoleMapper.countUserRoleByRoleId(roleId);
    }

    /**
     * 取消授权用户角色
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAuthUser(Long userId, Long roleId) {
        LambdaQueryWrapper<AppUserRole> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(AppUserRole::getUserId, userId)
                .eq(AppUserRole::getRoleId, roleId);
        return userRoleMapper.delete(wrapper) > 0;
    }

    /**
     * 批量取消授权用户角色
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAuthUsers(Long roleId, Long[] userIds) {
        LambdaQueryWrapper<AppUserRole> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(AppUserRole::getRoleId, roleId)
                .in(AppUserRole::getUserId, Arrays.asList(userIds));
        return userRoleMapper.delete(wrapper) > 0;
    }

    /**
     * 批量选择授权用户角色
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insertAuthUsers(Long roleId, Long[] userIds) {
        // 新增用户与角色管理
        List<AppUserRole> list = Arrays.stream(userIds).map(userId -> {
            AppUserRole ur = new AppUserRole();
            ur.setUserId(userId);
            ur.setRoleId(roleId);
            return ur;
        }).collect(Collectors.toList());
        return userRoleMapper.batchUserRole(list) > 0;
    }

}